﻿using System;
using System.Data.Entity;
using System.Linq;
using System.Reflection;
using System.Text;
using ExcellentCRM.DataService.Models;
using ExcellentCRM.DataService.Exts;

namespace ExcellentCRM.DataService
{
    public class DataServiceInitializer : DropCreateDatabaseIfModelChanges<DataServiceContext>
    {
        protected override void Seed(DataServiceContext dbCtx)
        {
            base.Seed(dbCtx);
            InitSetDefaultValue(dbCtx);
        }

        public void InitSetDefaultValue(DbContext dbCtx)
        {
            var modelTypes =
                dbCtx.GetType()
                     .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                     .Where(p => p.PropertyType.IsGenericType &&
                                 typeof (BaseModel).IsAssignableFrom(p.PropertyType.GenericTypeArguments[0]))
                     .Select(p => p.PropertyType.GenericTypeArguments[0]);
            var setBaseModelDefaultValueMethod =
                typeof (DataServiceInitializer).GetMethod("SetBaseModelPropertiesDefaultValue",
                                                          BindingFlags.NonPublic |
                                                          BindingFlags.Instance);
            foreach (var modelType in modelTypes)
            {
                var genericMehtod = setBaseModelDefaultValueMethod.MakeGenericMethod(modelType);
                genericMehtod.Invoke(this, new object[] {dbCtx});
            }
        }

        private void SetBaseModelPropertiesDefaultValue<T>(DbContext dbCtx)
            where T : BaseModel
        {
            var sbDfSql = new StringBuilder();
            try
            {
                string tableName = dbCtx.GetTableName<T>();
                sbDfSql.AppendLine(GenerateDefaultConstraintSql(tableName, "CreatedTime",
                                                                "getdate()"));
                sbDfSql.AppendLine(GenerateDefaultConstraintSql(tableName, "LastModifiedTime",
                                                                "getdate()"));
                sbDfSql.AppendLine(GenerateDefaultConstraintSql(tableName, "StatusToken", "1"));
                dbCtx.Database.ExecuteSqlCommand(sbDfSql.ToString());
            }
            catch (Exception ex)
            {
                throw new Exception(sbDfSql.ToString());
            }
        }

        private string GenerateDefaultConstraintSql(string tableName, string propertyName,
                                                    string defaultVal)
        {
            string simpleTableName = tableName.IndexOf('.') > -1
                                         ? tableName.Substring(tableName.IndexOf('.') + 1)
                                         : tableName;
            simpleTableName = simpleTableName.Trim(new[] {'[', ']'});
            string dfConstraintName = string.Format("DF_{0}_{1}", simpleTableName, propertyName);
            string sql =
                string.Format(
                    "if object_id('{1}','D') is null ALTER TABLE {0} ADD constraint {1} DEFAULT ({3}) FOR {2};",
                    tableName, dfConstraintName, propertyName, defaultVal);
            return sql;
        }
    }
}